package org.voovan.korla.rpc;

import org.voovan.korla.exception.KorlaException;
import org.voovan.korla.rpc.annotation.Rpc;
import org.voovan.tools.TEnv;
import org.voovan.tools.log.Logger;
import org.voovan.tools.reflect.TReflect;

import java.lang.reflect.Method;
import java.util.List;

import static org.voovan.korla.rpc.RpcStatic.RPC_METHODS;
import static org.voovan.korla.rpc.RpcStatic.RPC_SINGLETON_OBJECTS;

/**
 * Rpc方法和类扫描器
 *
 * @author: helyho
 * korla Framework.
 * WebSite: https://github.com/helyho/korla
 * Licence: Apache v2 License
 */
public class RpcScaner {
    /**
     * Rpc方法扫描
     * @param scanPackage 扫描的目标包路径
     */
    public static void scan(String scanPackage) {
        try {
            RPC_SINGLETON_OBJECTS.put(RpcStatic.class, new RpcStatic());

            List<Class> rpcClasses = TEnv.searchClassInEnv(scanPackage, new Class[]{Rpc.class});
            for (Class rpcClass : rpcClasses) {
                Rpc classAnnotation = (Rpc) rpcClass.getAnnotation(Rpc.class);
                //如果是单例,则创建单例对象
                if (classAnnotation.singleton()) {
                    RPC_SINGLETON_OBJECTS.put(rpcClass, TReflect.newInstance(rpcClass));
                }

                for (Method method : rpcClass.getDeclaredMethods()) {
                    Rpc methodAnnotation = method.getAnnotation(Rpc.class);
                    //注册方法
                    if (methodAnnotation != null) {;
                        RpcMethod rpcMethod = RpcMethod.newInstance(classAnnotation.value(), methodAnnotation, method);

                        if(RPC_METHODS.putIfAbsent(rpcMethod.getName(), rpcMethod)!=null){
                            throw new KorlaException("Rpc method name " + rpcMethod.getName() + " is exists");
                        } else {
                            Logger.simple("[RPC] Registed method name: "+ rpcMethod.getName());
                        }
                    }
                }
            }
        } catch (Exception e) {
            Logger.error("RpcScaner.scan(\"" + scanPackage + "\") failed,", e);
        }
    }
}
